home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 18 / CU Amiga Magazine's Super CD-ROM 18 (1997)(EMAP Images)(GB)[!][issue 1998-01].iso / CUCD / Programming / AmigaE / Src / Rkrm / Graphics_Libraries / Sprites_Bobs / collide.e < prev    next >
Encoding:
Text File  |  1995-09-20  |  20.0 KB  |  515 lines

  1. -> collide.e - An example of collision detection between objects and between
  2. ->             the border.
  3.  
  4. ->>> Header (globals)
  5. OPT PREPROCESS
  6.  
  7. MODULE 'dos/dos',
  8.        'exec/memory',
  9.        'graphics/collide',
  10.        'graphics/gels',
  11.        'graphics/gfx',
  12.        'graphics/rastport',
  13.        'graphics/view',
  14.        'intuition/intuition',
  15.        'intuition/screens',
  16.        'other/ecode',
  17.        '*animtools'
  18.  
  19. ENUM ERR_NONE, ERR_RAST, ERR_SCRN, ERR_WIN
  20.  
  21. RAISE ERR_RAST IF AllocRaster()=NIL,
  22.       ERR_SCRN IF OpenScreen()=NIL,
  23.       ERR_WIN  IF OpenWindow()=NIL
  24.  
  25. CONST RBMWIDTH=320, RBMHEIGHT=200, RBMDEPTH=4
  26.  
  27. -> These give the number of frames (COUNT), size (HEIGHT, WIDTH, DEPTH), and
  28. -> word width (WWIDTH) of the animated object.
  29. CONST BOING_COUNT=6, BOING_HEIGHT=25, BOING_WIDTH=32, BOING_DEPTH=1
  30. CONST BOING_WWIDTH=BOING_WIDTH+15/16
  31.  
  32. -> These are the IDs for the system to use for the three objects.  These
  33. -> numbers will be used for the collision detection system.
  34. ->
  35. -> Do not use zero (0), as it is reserved by the collision system for border
  36. -> hits (see 'graphics/collide', BORDERHIT).
  37. ENUM BOING_1=2, BOING_2, BOING_3
  38.  
  39. DEF ns:PTR TO ns, nw:PTR TO nw, boing3Times:PTR TO INT,
  40.     boing3YTranses:PTR TO INT, boing3XTranses:PTR TO INT,
  41.     boing3CRoutines:PTR TO LONG, boing3Image:PTR TO LONG,
  42.     newBoingBob:PTR TO newBob, newBoingSeq:PTR TO newAnimSeq
  43.  
  44. -> E-Note: this is the static variable from setupBitMaps().
  45. DEF myBitMaps[2]:ARRAY OF LONG
  46. ->>>
  47.  
  48. ->>> PROC setupGlobals()
  49. PROC setupGlobals()
  50.   ns:=[0, 0, 320, 200, 2, 0, 1, NIL,
  51.        CUSTOMSCREEN, NIL, 'Collision with AnimObs', NIL, NIL]:ns
  52.   nw:=[50, 50, 220, 100, -1, -1, IDCMP_CLOSEWINDOW,
  53.        WFLG_CLOSEGADGET OR WFLG_RMBTRAP, NIL, NIL, 'Close Window to Stop',
  54.        NIL, NIL, 150, 100, 150, 100, CUSTOMSCREEN]:nw
  55.   -> These are the number of counts that each frame is displayed.  They are
  56.   -> all one, so each frame is displayed once then the animation system will
  57.   -> move on to the next in the sequence.
  58.   boing3Times:=[1, 1, 1, 1, 1, 1]:INT
  59.   -> These are all set to zero as we do not want anything added to the X and Y
  60.   -> positions using ring motion control.  All movement is done using the
  61.   -> acceleration and velocity values.
  62.   boing3YTranses:=[0, 0, 0, 0, 0, 0]:INT
  63.   boing3XTranses:=[0, 0, 0, 0, 0, 0]:INT
  64.   -> No special routines to call when each anim comp is displayed.
  65.   boing3CRoutines:=[NIL, NIL, NIL, NIL, NIL, NIL]:LONG
  66.   boing3Image:=copyListToChip(
  67.                              -> ----- bitmap Boing, frame 0:  w = 32, h = 25 ------
  68.                              [$00230000, $004E3000, $00E33A00, $03C3C900,
  69.                               $07878780, $108F8700, $31F78790, $61F04790,
  70.                               $63E0FB90, $43E0F848, $3BC0F870, $3801F870,
  71.                               $383DF070, $387E1070, $387C0EE0, $D87C1F10,
  72.                               $467C1E10, $479C1E30, $67873E20, $0787CC60,
  73.                               $0F0F8700, $048F0E00, $02771C00, $0161D800,
  74.                               $00272000,
  75.                              -> ----- bitmap Boing, frame 1:  w = 32, h = 25 ------
  76.                               $00318000, $01071800, $00F01900, $09E1EC80,
  77.                               $13C1E340, $1803E380, $387BC390, $30F801D0,
  78.                               $70F83DC0, $E1F03E08, $9DF07C30, $9E307C30,
  79.                               $9E1C7C30, $1C1F9C30, $1C1F0630, $7C1F0780,
  80.                               $623F0798, $63DE0F10, $23C10F20, $33C3EE20,
  81.                               $0BC3C380, $0647C700, $023F8E00, $0130F800,
  82.                               $00338000,
  83.                              -> ----- bitmap Boing, frame 2:  w = 32, h = 25 ------
  84.                               $0019C000, $01038800, $02788D00, $0CF0FE80,
  85.                               $11F0F140, $0E60F1E0, $1C39F0C0, $1C3E30C0,
  86.                               $387E0CE0, $F87C1F28, $8C7C1F18, $8F3C1F18,
  87.                               $8F061E18, $8F07DE18, $8F07C018, $6E0FC1C0,
  88.                               $300F83C8, $31EF8390, $31F08780, $11E0F720,
  89.                               $11E1F1C0, $0B61E300, $071BC600, $01386C00,
  90.                               $00318000,
  91.                              -> ----- bitmap Boing, frame 3:  w = 32, h = 25 ------
  92.                               $001CE000, $01B1CC00, $031CC500, $0C3C3680,
  93.                               $18787840, $2F7078E0, $0E087860, $1E0FB860,
  94.                               $1C1F0460, $BC1F07B0, $C43F0788, $C7FE0788,
  95.                               $C7C00F88, $C781EF88, $C783F118, $2783E0E8,
  96.                               $3983E1E0, $3863E1C0, $1878C1C0, $38783380,
  97.                               $10F078C0, $0B70F180, $0588E200, $009E2400,
  98.                               $0018C000,
  99.                              -> ----- bitmap Boing, frame 4:  w = 32, h = 25 ------
  100.                               $000E6000, $00F8E400, $030FE600, $061E1300,
  101.                               $0C3E1C80, $27FC1C60, $07843C60, $4F07FE20,
  102.                               $8F07C230, $1E0FC1F0, $620F83C8, $61CF83C8,
  103.                               $61E183C8, $63E063C8, $63E0F9C8, $03E0F878,
  104.                               $1DC0F860, $1C21F0E0, $5C3EF0C0, $0C3C11C0,
  105.                               $143C3C40, $09B83880, $05C07000, $00CF0400,
  106.                               $000C6000,
  107.                              -> ----- bitmap Boing, frame 5:  w = 32, h = 25 ------
  108.                               $00262000, $00FC7400, $01877200, $030F0100,
  109.                               $0E0F0E80, $319F0E00, $23C60F30, $63C1CF30,
  110.                               $4781F310, $0783E0D0, $7383E0E0, $70C3E0E0,
  111.                               $70F9E1E0, $70F821E0, $70F83FE0, $91F03E38,
  112.                               $4FF07C30, $4E107C60, $4E0F7860, $2E1F08C0,
  113.                               $0E1E0E00, $049E1C80, $00E43800, $00C79000,
  114.                               $000E6000])
  115.   -> These objects contain the initialisation data for the animation sequence.
  116.   newBoingBob:=[NIL, BOING_WWIDTH, BOING_HEIGHT, BOING_DEPTH, $2, $0,
  117.                 VSF_SAVEBACK OR VSF_OVERLAY, 0, RBMDEPTH, 0, 0, 0, 0]:newBob
  118.   newBoingSeq:=[NIL, boing3Image, boing3XTranses, boing3YTranses,
  119.                 boing3Times, boing3CRoutines, 0, BOING_COUNT, 0]:newAnimSeq
  120. ENDPROC
  121. ->>>
  122.  
  123. ->>> PROC setupBoing(dbufing)
  124. -> Make a new animation object.  Since all of the boing balls use the same
  125. -> underlying data, the initalisation structures are hard-coded into the
  126. -> routine (newBoingBob and newBoingSeq.)
  127. ->
  128. -> Return a pointer to the object if successful.
  129. PROC setupBoing(dbufing) HANDLE
  130.   DEF bngOb=NIL:PTR TO ao, bngComp:PTR TO ac
  131.   NEW bngOb
  132.   newBoingBob.dBuf:=dbufing  -> Double-buffer status
  133.   newBoingSeq.headOb:=bngOb  -> Pass down head object
  134.  
  135.   bngComp:=makeSeq(newBoingBob, newBoingSeq)
  136.   -> The head comp is the one that is returned by makeSeq()
  137.   bngOb.headcomp:=bngComp
  138. EXCEPT
  139.   IF bngOb THEN END bngOb
  140.   ReThrow()
  141. ENDPROC bngOb
  142. ->>>
  143.  
  144. ->>> PROC runAnimation(win:PTR TO window, dbufing, animKey, myBitMaps)
  145. -> A simple message handling LOOP that also draws the successive frames.
  146. PROC runAnimation(win:PTR TO window, dbufing, animKey, myBitMaps)
  147.   DEF intuiMsg:PTR TO intuimessage, toggleFrame
  148.   -> toggleFrame is used to keep track of which frame of the double buffered
  149.   -> screen we are currently displaying.  The variable must exist for the life
  150.   -> of the displayed objects, so it is defined here.
  151.   toggleFrame:=0
  152.  
  153.   -> End the loop on a IDCMP_CLOSEWINDOW event.
  154.   LOOP
  155.     -> Draw the gels, then check for messages.  Check the messages after each
  156.     -> display so we get a quick response.
  157.     drawGels(win, animKey, dbufing, {toggleFrame}, myBitMaps)
  158.  
  159.     -> Quit on a Control-C
  160.     -> E-Note: use built-in check
  161.     IF CtrlC() THEN RETURN
  162.  
  163.     -> Check for a IDCMP_CLOSEWINDOW event, die if found
  164.     WHILE intuiMsg:=GetMsg(win.userport)
  165.       IF intuiMsg.class=IDCMP_CLOSEWINDOW
  166.         ReplyMsg(intuiMsg)
  167.         RETURN
  168.       ENDIF
  169.       ReplyMsg(intuiMsg)
  170.     ENDWHILE
  171.   ENDLOOP
  172. ENDPROC
  173. ->>>
  174.  
  175. ->>> PROC setupPlanes(bitMap:PTR TO bitmap, depth, width, height)
  176. -> Called only for double-buffered displays.  Allocate and clear each
  177. -> bit-plane in a bitmap structure.  Clean-up on failure.
  178. PROC setupPlanes(bitMap:PTR TO bitmap, depth, width, height) HANDLE
  179.   DEF plane_num
  180.   FOR plane_num:=0 TO depth-1
  181.     bitMap.planes[plane_num]:=AllocRaster(width, height)
  182.     BltClear(bitMap.planes[plane_num], (width/8)*height, 1)
  183.   ENDFOR
  184. EXCEPT
  185.   freePlanes(bitMap, depth, width, height)
  186.   ReThrow()
  187. ENDPROC
  188. ->>>
  189.  
  190. ->>> PROC setupBitMaps(depth, width, height)
  191. -> Allocate the two bitmaps for a double-buffered display.  Routine only
  192. -> called when the display is double-buffered.
  193. PROC setupBitMaps(depth, width, height) HANDLE
  194.   DEF p=NIL:PTR TO bitmap, q=NIL:PTR TO bitmap
  195.   -> Allocate the two bitmap objects.  These do not have to be in CHIP.
  196.   -> E-Note: use p and q to get correct type.
  197.   myBitMaps[0]:=NEW p
  198.   myBitMaps[1]:=NEW q
  199.   -> Initialise the bitmaps to the correct size.
  200.   InitBitMap(p, depth, width, height)
  201.   InitBitMap(q, depth, width, height)
  202.   -> Allocate and initialise the bit-planes for the bitmaps.
  203.   setupPlanes(p, depth, width, height)
  204.   setupPlanes(q, depth, width, height)
  205. EXCEPT
  206.   IF p
  207.     freePlanes(p, depth, width, height)
  208.     END p
  209.   ENDIF
  210.   IF q
  211.     freePlanes(q, depth, width, height)
  212.     END q
  213.   ENDIF
  214.   ReThrow()
  215. ENDPROC myBitMaps
  216. ->>>
  217.  
  218. ->>> PROC freePlanes(bitMap:PTR TO bitmap, depth, width, height)
  219. -> Free all of the bit-planes in a bitmap structure.
  220. PROC freePlanes(bitMap:PTR TO bitmap, depth, width, height)
  221.   DEF plane_num
  222.   FOR plane_num:=0 TO depth-1
  223.     IF bitMap.planes[plane_num]
  224.       FreeRaster(bitMap.planes[plane_num], width, height)
  225.     ENDIF
  226.   ENDFOR
  227. ENDPROC
  228. ->>>
  229.  
  230. ->>> PROC freeBitMaps(myBitMaps:PTR TO LONG, depth, width, height)
  231. -> Free the two bitmaps from the double buffered display. The bit-planes are
  232. -> freed first, then the bitmap objects.
  233. PROC freeBitMaps(myBitMaps:PTR TO LONG, depth, width, height)
  234.   freePlanes(myBitMaps[0], depth, width, height)
  235.   freePlanes(myBitMaps[1], depth, width, height)
  236.   END myBitMaps[2]
  237. ENDPROC
  238. ->>>
  239.  
  240. ->>> PROC setupDisplay(win:PTR TO LONG, dbufing, myBitMaps:PTR TO LONG)
  241. -> Open the screen and the window for the display.
  242. ->
  243. -> If using double buffered display, assume the bitmaps have been opened and
  244. -> correctly set-up.
  245. PROC setupDisplay(win:PTR TO LONG, dbufing, myBitMaps:PTR TO LONG) HANDLE
  246.   DEF gInfo, screen=NIL, wp=NIL:PTR TO window
  247.   -> If double-buffered, set-up the new screen structure for custom bitmap.
  248.   IF dbufing
  249.     ns.type:=ns.type OR CUSTOMBITMAP
  250.     ns.custombitmap:=myBitMaps[0]
  251.   ENDIF
  252.  
  253.   -> Open everything.  Check for failure.
  254.   screen:=OpenScreen(ns)
  255.   nw.screen:=screen
  256.   -> E-Note: use wp to get the right type
  257.   win[]:=(wp:=OpenWindow(nw))
  258.   IF dbufing
  259.     -> We are double buffered.  Set the rastport for it.
  260.     wp.wscreen.rastport.flags:=RPF_DBUFFER
  261.  
  262.     -> This copies the Intuition display (close gadget) to the second bitmap
  263.     -> so the display does not flash when we change between them.
  264.     wp.wscreen.rastport.bitmap:=myBitMaps[1]
  265.     BltBitMapRastPort(myBitMaps[0], 0, 0, wp.wscreen.rastport,
  266.                       0, 0, RBMWIDTH, RBMHEIGHT, $C0)
  267.     wp.wscreen.rastport.bitmap:=myBitMaps[0]
  268.   ENDIF
  269.  
  270.   -> Ready the gel system for accepting objects.  This is only done once for
  271.   -> each rastport in use.
  272.   gInfo:=setupGelSys(wp.wscreen.rastport, $03)
  273. EXCEPT
  274.   IF wp THEN CloseWindow(wp)
  275.   IF screen THEN CloseScreen(screen)
  276.   ReThrow()
  277. ENDPROC gInfo
  278. ->>>
  279.  
  280. ->>> PROC drawGels(win:..., animKey, dbufing, toggleFrame:..., myBitMaps:...)
  281. -> Handle the update of the display.  Animate the simulation and check for
  282. -> collisions.  If the screen is double buffered, swap the bit map as
  283. -> required.
  284. -> E-Note: toggleFrame is PTR TO LONG since '{toggle}' was used.
  285. PROC drawGels(win:PTR TO window, animKey, dbufing,
  286.               toggleFrame:PTR TO LONG, myBitMaps:PTR TO LONG)
  287.   -> Do the required animation stuff.  You must sort both after the animate
  288.   -> call and after the collision call.
  289.   Animate(animKey, win.wscreen.rastport)
  290.   SortGList(win.wscreen.rastport)
  291.  
  292.   DoCollision(win.wscreen.rastport)
  293.   SortGList(win.wscreen.rastport)
  294.  
  295.   -> Toggle if double buffered
  296.   IF dbufing
  297.     win.wscreen.viewport.rasinfo.bitmap:=myBitMaps[toggleFrame[]]
  298.   ENDIF
  299.  
  300.   -> Draw the new position of the gels into the screen.
  301.   DrawGList(win.wscreen.rastport, win.wscreen.viewport)
  302.  
  303.   -> If using a double buffered display, you have a more complicated update
  304.   -> procedure.  If not then simply use WaitTOF().
  305.   IF dbufing
  306.     MakeScreen(win.wscreen)
  307.     RethinkDisplay()
  308.     toggleFrame[]:=1-toggleFrame[]
  309.     win.wscreen.rastport.bitmap:=myBitMaps[toggleFrame[]]
  310.   ELSE
  311.     WaitTOF()
  312.   ENDIF
  313. ENDPROC
  314. ->>>
  315.  
  316. ->>> PROC bounceWall(vs1:PTR TO vs, borderflags)
  317. -> Handle bouncing the animation objects off the walls.
  318. PROC bounceWall(vs1:PTR TO vs, borderflags)
  319.   DEF ob:PTR TO ao
  320.   -> Get a pointer to the object from the sprite pointer.
  321.   ob:=vs1.vsbob.bobcomp.headob
  322.  
  323.   -> Check for hits and act appropriately.  For right and left, reverse the x
  324.   -> velocity if the object is moving towards the wall (it may have already
  325.   -> reversed but still be in contact with the wall).  For the bottom and top
  326.   -> you also have to subtract out the velocity.
  327.   IF ((borderflags AND RIGHTHIT) AND (ob.xvel>0)) OR
  328.      ((borderflags AND LEFTHIT) AND (ob.xvel<0))
  329.     ob.xvel:=-ob.xvel
  330.   ELSEIF ((borderflags AND TOPHIT) AND (ob.yvel<0)) OR
  331.          ((borderflags AND BOTTOMHIT) AND (ob.yvel>0))
  332.     ob.yvel:=ob.yvel-ob.yaccel
  333.     ob.yvel:=-ob.yvel
  334.   ENDIF
  335. ENDPROC
  336. ->>>
  337.  
  338. ->>> PROC hit_routine(vs1:PTR TO vs, vs2:PTR TO vs)
  339. -> Handle the collision between two animation objects.  This routine simulates
  340. -> objects bouncing off of each other.  This does not do a very good job of
  341. -> it, it does not take into account the angle of the collision or real
  342. -> physics. If anyone wants to fix it, please feel free.
  343. ->
  344. -> The call to DoCollision() causes a call back to this routine when two
  345. -> animation objects overlap.
  346. PROC hit_routine(vs1:PTR TO vs, vs2:PTR TO vs)
  347.   DEF vel1, vel2, ob1:PTR TO ao, ob2:PTR TO ao
  348.   -> Get pointers to the objects from the sprite pointers.
  349.   ob1:=vs1.vsbob.bobcomp.headob
  350.   ob2:=vs2.vsbob.bobcomp.headob
  351.  
  352.   -> Check that the bob is not being removed!  This is due to a 1.3 bug where
  353.   -> all bobs are tested for collision, even the ones that are in the process
  354.   -> of being removed.  See text for more information.
  355.   ->
  356.   -> Bobs are moved to a very large negative position as they are being
  357.   -> removed.  If the BOBSAWAY flag is set, then both bobs in the collision
  358.   -> are in the process of being removed--don't do anything in the collision
  359.   -> routine.
  360.   IF 0=(vs1.vsbob.bobflags AND BF_BOBSAWAY)
  361.     -> Cache the velocity values.
  362.     -> Do the X values first (order is not important).
  363.     vel1:=ob1.xvel
  364.     vel2:=ob2.xvel
  365.  
  366.     -> If the two objects are moving in the opposite direction (X component)
  367.     -> then negate the velocities, else swap the velocities.
  368.     IF ((vel1>0) AND (vel2<0)) OR ((vel1<0) AND (vel2>0))
  369.       ob1.xvel:=-vel1
  370.       ob2.xvel:=-vel2
  371.     ELSE
  372.       ob1.xvel:=vel2
  373.       ob2.xvel:=vel1
  374.     ENDIF
  375.  
  376.     -> Cache the velocity values.
  377.     -> Do the Y values second (order is not important).
  378.     vel1:=ob1.yvel
  379.     vel2:=ob2.yvel
  380.  
  381.     -> If the two objects are moving in the opposite direction (Y component)
  382.     -> then negate the velocities, else swap the velocities.
  383.     IF ((vel1>0) AND (vel2<0)) OR ((vel1<0) AND (vel2>0))
  384.       ob1.yvel:=-vel1
  385.       ob2.yvel:=-vel2
  386.     ELSE
  387.       ob1.yvel:=vel2
  388.       ob2.yvel:=vel1
  389.     ENDIF
  390.   ENDIF
  391. ENDPROC
  392. ->>>
  393.  
  394. ->>> PROC main()
  395. -> Run a double buffered display if the user puts any arguments on the command
  396. -> line.
  397. ->
  398. -> Set-up the display, set-up the animation system and the objects, set-up
  399. -> collisions between objects and against walls, and run the thing.
  400. ->
  401. -> Clean-up and close resources when done.
  402. PROC main() HANDLE
  403.   DEF myBitMaps:PTR TO LONG, boingOb=NIL:PTR TO ao, boing2Ob=NIL:PTR TO ao,
  404.       boing3Ob=NIL:PTR TO ao, win=NIL:PTR TO window, gInfo=NIL, animKey,
  405.       dbufing=0, hitcode
  406.   -> E-Note: set-up global data
  407.   setupGlobals()
  408.   -> If any arguments, use double-buffering
  409.   IF arg THEN IF arg[] THEN dbufing:=1
  410.   WriteF(IF dbufing THEN
  411.          'Double buffering - no args means single buffered\n' ELSE
  412.          'Single buffering - supply any arguments to do double buffering\n')
  413.   -> Note that setupBitMaps() will only be called if we are double buffering.
  414.   IF dbufing THEN myBitMaps:=setupBitMaps(RBMDEPTH, RBMWIDTH, RBMHEIGHT)
  415.   gInfo:=setupDisplay({win}, dbufing, myBitMaps)
  416.   -> You have to initialise the animation key before you use it.
  417.   InitAnimate({animKey})
  418.  
  419.   -> Set-up the first boing ball.  All of these use the same data, hard coded
  420.   -> into setupBoing().  Change the colour by changing planePick.  Set the ID
  421.   -> of the ball (meMask) to BOING_1.  hitMask = $FF means that it will
  422.   -> collide with everything.
  423.   newBoingBob.planePick:=$2
  424.   newBoingBob.meMask:=Shl(1, BOING_1)
  425.   newBoingBob.hitMask:=$FF
  426.   boingOb:=setupBoing(dbufing)
  427.  
  428.   -> Pick an initial position, velocity and acceleration and add the OBJECT to
  429.   -> the system.  NOTE that the Y-velocity and X-acceleration are not set
  430.   -> (they default to zero.)  This means that the objects will maintain a
  431.   -> constant movement to the left or right, and will rely on the Y
  432.   -> accelleration for the downward movement.  The collision routines change
  433.   -> these values, producing bouncing off of walls and other objects.
  434.   ->
  435.   -> NOTE: ANFRACSIZE is a value that shifts animation constants past an
  436.   -> internal decimal point.  If you do not do this, then the values will only
  437.   -> be some fraction of what you expect.  See the text of the Animation
  438.   -> chapter.
  439.   boingOb.any:=Shl(10, ANFRACSIZE)
  440.   boingOb.anx:=Shl(250, ANFRACSIZE)
  441.   boingOb.xvel:=-Shl(3, ANFRACSIZE)
  442.   boingOb.yaccel:=35
  443.   AddAnimOb(boingOb, {animKey}, win.wscreen.rastport)
  444.  
  445.   -> Do the second object--see above comments.
  446.   newBoingBob.planePick:=$1
  447.   newBoingBob.meMask:=Shl(1, BOING_2)
  448.   newBoingBob.hitMask:=$FF
  449.   boing2Ob:=setupBoing(dbufing)
  450.   boing2Ob.any:=Shl(50, ANFRACSIZE)
  451.   boing2Ob.anx:=Shl(50, ANFRACSIZE)
  452.   boing2Ob.xvel:=Shl(2, ANFRACSIZE)  
  453.   boing2Ob.yaccel:=35
  454.   AddAnimOb(boing2Ob, {animKey}, win.wscreen.rastport)
  455.  
  456.   -> Do the third object--see above comments.
  457.   -> Here we also use planeOnOff to change the colour.
  458.   newBoingBob.planePick:=$1
  459.   newBoingBob.planeOnOff:=$2
  460.   newBoingBob.meMask:=Shl(1, BOING_3)
  461.   newBoingBob.hitMask:=$FF
  462.   boing3Ob:=setupBoing(dbufing)
  463.   boing3Ob.any:=Shl(80, ANFRACSIZE)
  464.   boing3Ob.anx:=Shl(150, ANFRACSIZE)
  465.   boing3Ob.xvel:=Shl(1, ANFRACSIZE)
  466.   boing3Ob.yaccel:=35
  467.   AddAnimOb(boing3Ob, {animKey}, win.wscreen.rastport)
  468.  
  469.   -> Set up the collisions between boing balls.
  470.   -> NOTE that they all call the same routine.
  471.   -> E-Note: wrap hit_routine() so it can be used as a collision function (the
  472.   ->         function is simple enough not to need the full register
  473.   ->         preservation of eCodeCollision(), so eCodeSwapArgs() is used).
  474.   hitcode:=eCodeSwapArgs({hit_routine})
  475.   SetCollision(BOING_1, hitcode, gInfo)
  476.   SetCollision(BOING_2, hitcode, gInfo)
  477.   SetCollision(BOING_3, hitcode, gInfo)
  478.  
  479.   -> Set the collisions with the walls.
  480.   -> E-Note: see above comment about eCodeXXX().
  481.   SetCollision(BORDERHIT, eCodeSwapArgs({bounceWall}), gInfo)
  482.  
  483.   -> Everything set-up...  Run the animation.
  484.   runAnimation(win, dbufing, {animKey}, myBitMaps)
  485.  
  486.   -> Done..  Free-up everything and clean up the mess.
  487. EXCEPT DO
  488.   IF boing3Ob THEN freeOb(boing3Ob, RBMDEPTH)
  489.   IF boing2Ob THEN freeOb(boing2Ob, RBMDEPTH)
  490.   IF boingOb THEN freeOb(boingOb, RBMDEPTH)
  491.   IF gInfo THEN cleanupGelSys(gInfo, win.wscreen.rastport)
  492.   IF win THEN CloseWindow(win)
  493.   -> E-Note: C version does not do this safely...
  494.   IF nw.screen THEN CloseScreen(nw.screen)
  495.   IF dbufing THEN freeBitMaps(myBitMaps, RBMDEPTH, RBMWIDTH, RBMHEIGHT)
  496.   SELECT exception
  497.   CASE ERR_RAST;  WriteF('Error: could not allocate raster\n')
  498.   CASE ERR_SCRN;  WriteF('Error: could not open screen\n')
  499.   CASE ERR_WIN;   WriteF('Error: could not open window\n')
  500.   CASE "MEM";     WriteF('Error: ran out of memory\n')
  501.   ENDSELECT
  502. ENDPROC IF exception<>ERR_NONE THEN RETURN_FAIL ELSE RETURN_OK
  503. ->>>
  504.  
  505. ->>> PROC copyListToChip(data)
  506. -> E-Note: get some Chip memory and copy list (quick, since LONG aligned)
  507. PROC copyListToChip(data)
  508.   DEF size, mem
  509.   size:=ListLen(data)*SIZEOF LONG
  510.   mem:=NewM(size, MEMF_CHIP)
  511.   CopyMemQuick(data, mem, size)
  512. ENDPROC mem
  513. ->>>
  514.  
  515.